﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ADDDF.Infrastructure.Test
{
    [TestClass]
    public class EntityBaseUnitTest
    {
        [TestMethod]
        public void EntityBase_Constructor()
        {
            PartyEntity p1 = new PartyEntity(EntityHelper.NewKey(), "Safety Lights Co.");

            PartyEntity p2 = new PartyEntity(30, "Five Guys");

            Assert.AreEqual(30, p2.Key);

            // 9/19/2012: Allow passing null as key to the constructor.
            //try
            //{
            //    PartyEntity p3 = new PartyEntity(null, "ToysRUs");

            //    Assert.Fail("Expect D3InvalidArgumentException when construct with null key");
            //}
            //catch (D3InvalidArgumentException)
            //{
            //}
        }

        [TestMethod]
        public void EntityBase_Equal_Test()
        {
            PartyEntity p1 = new PartyEntity(EntityHelper.NewKey(), "Best Buy");
            PartyEntity p2 = new PartyEntity(30, "Fry's Electronics");
            PartyEntity p3 = new PartyEntity(30, "Fry's Electronics / Instance 2");
            PartyEntity p4 = new PartyEntity(80, "Fry's Electronics");
            PartyEntity p5 = new PartyEntity(EntityHelper.NewKey(), "CompUSA");

            //10/4/12: Changed behavior. It's ok to compare a entities with non-null Key to one that has null-key
            //try
            //{
            //    p1.SameKeyAs(p2);
            //    Assert.Fail("Expect D3NullKeyException when compare entity with null keys");
            //}
            //catch (D3NullKeyException)
            //{
            //}

            //10/4/12: Changed behavior. It's ok to compare a entities with non-null Key to one that has null-key
            //try
            //{
            //    p2.SameKeyAs(p1);
            //    Assert.Fail("Expect D3NullKeyException when compare entity with null keys");
            //}
            //catch (D3NullKeyException)
            //{
            //}

            //10/4/12: Changed behavior. It's ok to compare a entities with non-null Key to one that has null-key
            // Comparing 2 entitities both with null key will result in exception.
            //try
            //{
            //    p1.SameTypeAndKeyAs(p5);
            //    Assert.Fail("Expect D3NullKeyException when compare entity with null keys");
            //}
            //catch (D3NullKeyException)
            //{
            //}

            //10/4/12: Changed behavior. It's ok to compare a entities with non-null Key to one that has null-key
            Assert.IsFalse(p1.SameKeyAs(p2));
            Assert.IsFalse(p2.SameKeyAs(p1));

            Assert.IsTrue(p2.SameKeyAs(p3));
            //Assert.IsTrue(p2 == p3);
            //Assert.IsTrue(p2.Equals(p3));
            //Assert.IsFalse(p2 != p3);

            Assert.IsFalse(p2.SameKeyAs(p4));
            //Assert.IsFalse(p2 == p4);
            //Assert.IsFalse(p2.Equals(p4));
            //Assert.IsTrue(p2 != p4);

            //try
            //{
            //    int hash = p1.GetHashCode();
            //    Assert.Fail("Expect D3NullKeyException when GetHashCode from entity with null keys");
            //}
            //catch (D3NullKeyException)
            //{
            //}

            //Assert.AreNotEqual(0, p2.GetHashCode());
        }

        [TestMethod]
        public void EntityBase_UseKeyInDictionary()
        {
            Random rand = new Random(0);
            HashSet<int> expected = new HashSet<int>();
            Dictionary<object, PartyEntity> actual = new Dictionary<object, PartyEntity>();

            for (int i = 0; i < 1000; i++)
            {
                int id = rand.Next(1, 100);

                bool keyIsInExpected = expected.Contains(id);
                bool keyIsInActual = actual.ContainsKey(id);

                Assert.AreEqual(keyIsInExpected, keyIsInActual);

                if (!keyIsInActual)
                {
                    expected.Add(id);

                    PartyEntity p0 = new PartyEntity(id, "some company " + id.ToString());

                    actual.Add(p0.Key, p0);
                }                    
            }
        }
    }
}
